/*******************************************************************************
** www.IfcGears.com                                                           **
** Copyright (C) 2010 - Bauhaus University Weimar, www.uni-weimar.de          **
** Written: 2010-10-02, Fabian Gerold, www.fabiangerold.de                    **
*******************************************************************************/

#include "MainWindow.h"
#include "FileWidget.h"
#include "gears/IfcGears.h"
#include <QtGui>

MainWindow::MainWindow( IfcGears* class_generator, QWidget *parent ) : QMainWindow(parent)
{
	m_class_generator = class_generator;
	setWindowTitle( QString("IfcGearsExtender - Class and Parser Generator - www.ifcgears.com") );
	setWindowIcon( QIcon( ":Resources/img/IfcGearsWindowIcon.png" ) );
	QFile file( ":Resources/styles.css" );
	file.open( QFile::ReadOnly );
	QString styleSheet = QLatin1String( file.readAll() );
	setStyleSheet( styleSheet );

	int left_panel_width = 160;

	QPushButton* btn_add_schema_file = new QPushButton( "Add other schema file" );
	connect( btn_add_schema_file, SIGNAL( clicked() ), this, SLOT( slotAddOtherSchemaFileClicked() ) );

	QStringList schema_files;
	schema_files << "IFC2X4_RC3.exp" << "IFC2X3_TC1.exp";// << "IFCBridgeV2R8.exp";

	m_table_schema_files = new QTableWidget(this);
	m_table_schema_files->setRowCount( schema_files.size() );
	m_table_schema_files->setColumnCount(2);
	m_table_schema_files->setColumnWidth( 0, left_panel_width-36 );
	m_table_schema_files->setColumnWidth( 1, 36 );
	m_table_schema_files->setMaximumWidth( left_panel_width );
	m_table_schema_files->horizontalHeader()->hide();
	m_table_schema_files->verticalHeader()->hide();


	int table_row = 0;
	foreach( QString schema_file, schema_files )
	{
		// label
		m_table_schema_files->setItem( table_row, 0, new QTableWidgetItem( schema_file ) );

		// "load" button
		QPushButton* btn_load_schema = new QPushButton( "Load" );
		btn_load_schema->setStyleSheet( "padding: 1px 1px 1px 1px;min-width: 30px;" );
		m_table_schema_files->setCellWidget( table_row, 1, btn_load_schema );
		connect( btn_load_schema, SIGNAL(clicked()),	this,	SLOT( slotLoadSchemaClicked() ) );
		m_map_btnload_tablerow.insert( std::pair<QPushButton*, int>(btn_load_schema, table_row) );

		m_table_schema_files->setRowHeight( table_row, 16 );
		++table_row;
	}
	QTableWidgetSelectionRange range( 0, 0, 0, 0 );
	m_table_schema_files->setRangeSelected( range, true );


	m_files_tab = new QTabWidget;
	m_files_tab->setTabsClosable( true );
	connect( m_files_tab, SIGNAL( tabCloseRequested(int) ), this, SLOT( slotTabCloseRequested(int) ) );

	// options
	QLineEdit* le_smart_pointers = new QLineEdit;
	le_smart_pointers->setText( "std::tr1::shared_ptr<T>" ); 
	le_smart_pointers->setDisabled( true );

//	m_le_namespace = new QLineEdit( m_class_generator->getNamespace() );
	//m_le_namespace->setDisabled( true );

	QCheckBox* checkbox_include_comments = new QCheckBox;
	checkbox_include_comments->setChecked( true );
	connect( checkbox_include_comments, SIGNAL( stateChanged(int) ), this, SLOT( slotIncludeComments(int) ) );

	// output
	//QString path_schema_file_out = "D:/work/NurbsStructure/src/";
	m_le_path_out = new QLineEdit( "D:/work/ifcgears/ifcgears/src" );
	//m_le_subfolder_ifc_classes_out = new QLineEdit( "IFC2X4" );

	m_btn_parse_schema = new QPushButton( "Generate all" );
	connect( m_btn_parse_schema, SIGNAL( clicked() ), this, SLOT( slotParseSchemaClicked() ) );
	//btn_parse_schema->setFocus();
	//btn_parse_schema->setDefault( true );

	m_txt_out = new QTextEdit;
	connect( class_generator, SIGNAL( signalTxtOut( QString ) ),		this, SLOT( slotTxtOut( QString ) ) );
	connect( class_generator, SIGNAL( signalTxtOutWarning( QString ) ), this, SLOT( slotTxtOutWarning( QString ) ) );

	m_progress_bar = new QProgressBar;
	m_progress_bar->setRange( 0, 1000 );
	connect( class_generator, SIGNAL(  signalProgressValue( int ) ),	this, SLOT( slotProgressValue( int ) ) );

	// recent files table
	m_table_recent_files = new QTableWidget(this);
	m_table_recent_files->setRowCount( 0 );
	m_table_recent_files->setColumnCount(2);
	m_table_recent_files->setColumnWidth( 0, left_panel_width-36 );
	m_table_recent_files->setColumnWidth( 1, 36 );
	m_table_recent_files->setMaximumWidth( left_panel_width );
	m_table_recent_files->horizontalHeader()->hide();
	m_table_recent_files->verticalHeader()->hide();


	QVBoxLayout* input_vbox = new QVBoxLayout;
	input_vbox->addWidget( new QLabel( "<b>Input</b>" ) );

	input_vbox->addWidget( m_table_schema_files, 0 );
	input_vbox->addSpacing( 10 );
	input_vbox->addWidget( btn_add_schema_file, 0 );
	input_vbox->addSpacing( 10 );
	input_vbox->addWidget( new QLabel( "Recent files: " ), 0 );
	input_vbox->addWidget( m_table_recent_files, 0 );
	input_vbox->addStretch( 1 );

	QGridLayout* grid_input = new QGridLayout;
	grid_input->addLayout( input_vbox, 0, 0 );
	grid_input->addWidget( m_files_tab, 0, 1 );
	grid_input->setColumnStretch( 0, 0 );
	grid_input->setColumnStretch( 1, 1 );
	grid_input->setColumnMinimumWidth( 0, left_panel_width );


	QGridLayout* grid_options = new QGridLayout;
	grid_options->addWidget( new QLabel( "<b>Options</b>" ), 0, 0 );

	grid_options->addWidget( new QLabel( "Smart pointers" ), 0, 1 );
	grid_options->addWidget( le_smart_pointers, 0, 2  );

	grid_options->addWidget( new QLabel( "Add comments" ), 1, 1 );
	grid_options->addWidget( checkbox_include_comments, 1, 2  );

	//grid_options->addWidget( new QLabel( "Namespace" ), 3, 1 );
	//grid_options->addWidget( m_le_namespace, 3, 2  );
	grid_options->setColumnMinimumWidth( 0, left_panel_width );
	grid_options->setColumnStretch( 0, 0 );
	grid_options->setColumnStretch( 1, 0 );
	grid_options->setColumnStretch( 3, 1 );


	QGridLayout* grid_output = new QGridLayout;
	grid_output->addWidget( new QLabel( "<b>Output</b>" ), 0, 0 );

	grid_output->addWidget( new QLabel( "Target folder (\"src/ifcgears/\" in your IfcGears download)" ), 0, 1 );
	grid_output->addWidget( m_le_path_out, 0, 2  );

	
	//grid_output->addWidget( new QLabel( "Subfolder for IFC classes (e.g. IFC2X4)" ), 1, 1 );
	//grid_output->addWidget( new QLabel( "IFC include file prefix (e.g. IFC2X4)" ), 1, 1 );
	//grid_output->addWidget( m_le_subfolder_ifc_classes_out, 1, 2  );

	grid_output->addWidget( m_btn_parse_schema, 2, 0  );
	//QLabel* generate_classes = new QLabel( "Generates classes, reader and writer" );
	//generate_classes->setWordWrap( true );
//	grid_output->addWidget( generate_classes, 3, 0  );

	grid_output->addWidget( m_txt_out,	2, 1, 2, 2 );
	grid_output->setRowStretch( 3, 1 );

	grid_output->addWidget( m_progress_bar,	4, 1, 1, 2 );
	grid_output->setColumnMinimumWidth( 0, left_panel_width );
	grid_output->setColumnStretch( 0, 0 );
	grid_output->setColumnStretch( 1, 0 );
	grid_output->setColumnStretch( 2, 1 );
	grid_output->setColumnStretch( 3, 0 );

	QWidget* input_widget = new QWidget;
	input_widget->setLayout( grid_input );

	QWidget* options_widget = new QWidget;
	options_widget->setLayout( grid_options );

	QWidget* output_widget = new QWidget;
	output_widget->setLayout( grid_output );

	QWidget* vbox_out_widget = new QWidget();
	QVBoxLayout* vbox_out = new QVBoxLayout(vbox_out_widget);
	vbox_out->addWidget( options_widget );
	vbox_out->addWidget( output_widget );

	QSplitter* splitter = new QSplitter( Qt::Vertical );
	splitter->addWidget( input_widget );
	splitter->addWidget( vbox_out_widget );
	splitter->setStretchFactor( 0, 2 );
	splitter->setStretchFactor( 1, 0 );

	QStatusBar* status = new QStatusBar;
	status->setSizeGripEnabled( true );
	setStatusBar( status );
	setCentralWidget( splitter );

	QSettings settings(QSettings::UserScope, QLatin1String("IfcGearsExtender"));

	bool clear_settings = false;
	if( clear_settings )
	{
		settings.clear();
	}

	QStringList keys = settings.allKeys();
	if( keys.contains( "MainWindow/geometry" ) )
	{
		restoreGeometry(settings.value("MainWindow/geometry").toByteArray());
	}
	else
	{
		setGeometry( 50, 50, 700, 900 );
	}
	if( keys.contains( "recentFiles" ) )
	{
		m_recent_files = settings.value("recentFiles").toStringList();
		QStringList opened_files = settings.value("openedFiles").toStringList();
		//opened_files.clear();
		if( opened_files.empty() )
		{
			opened_files << ":/Resources/IFC2X3_TC1.exp";
			opened_files << ":/Resources/IFC2X4_RC3.exp";
		}
		updateRecentFilesMenu();

		for( int i=0; i<opened_files.size(); ++i )
		{
			QString path_in = opened_files.at( i );
			slotAddSchemaFile( path_in );
		}
	}
	if( keys.contains( "pathOut" ) )
	{
		m_le_path_out->setText( settings.value("pathOut").toString() );
	}
}

MainWindow::~MainWindow()
{

}

void MainWindow::closeEvent(QCloseEvent *event)
{
	QStringList opened_files;
	for( int i=0; i<m_files_tab->count(); ++i )
	{
		FileWidget* fw = (FileWidget*)m_files_tab->widget( i );
		if( !fw )
		{
			continue;
		}
		opened_files << fw->getPathFile();
	}

	QSettings settings(QSettings::UserScope, QLatin1String("IfcGearsExtender"));
	settings.setValue("MainWindow/geometry", saveGeometry());
	settings.setValue("recentFiles",m_recent_files );
	settings.setValue("openedFiles",opened_files );
	settings.setValue("pathOut",m_le_path_out->text() );

	QWidget::closeEvent(event);
}

void MainWindow::slotAddOtherSchemaFileClicked()
{
	QFileDialog dialog( this );
	dialog.setFileMode( QFileDialog::ExistingFile );

	QStringList fileNames;
	if( dialog.exec() )
	{
		fileNames = dialog.selectedFiles();
	}

	if( fileNames.size() > 0 )
	{
		QString path_in = fileNames[0];
		slotAddSchemaFile( path_in );
		if( !m_recent_files.contains( path_in ) )
		{
			m_recent_files.push_back( path_in );
		}
	}
}

void MainWindow::updateRecentFilesMenu()
{
	int num_recent_files = std::min( 8, m_recent_files.size() );

	for( int table_row = 0; table_row < num_recent_files; ++table_row )
	{
		// label
		m_table_recent_files->setRowCount( table_row+1 );

		QTableWidgetItem* item = new QTableWidgetItem();
		item->setText( m_recent_files.at(table_row) );
		//
		//QLabel* item = new QLabel( m_recent_files.at(table_row) );
		item->setToolTip( m_recent_files.at(table_row) );
		//item->setTextAlignment( Qt::AlignRight );
		m_table_recent_files->setItem( table_row, 0, item );

		// "load" button
		QPushButton* btn_load_schema = new QPushButton( "Load" );
		btn_load_schema->setStyleSheet( "padding: 1px 1px 1px 1px;min-width: 30px;" );
		m_table_recent_files->setCellWidget( table_row, 1, btn_load_schema );
		connect( btn_load_schema, SIGNAL(clicked()),	this,	SLOT( slotLoadRecentFileClicked() ) );
		m_map_btnload_tablerow.insert( std::pair<QPushButton*, int>(btn_load_schema, table_row) );

		m_table_recent_files->setRowHeight( table_row, 16 );
	}
}

int MainWindow::slotAddSchemaFile( QString path_in )
{
	// sort out duplicates
	for( int i=0; i<m_files_tab->count(); ++i )
	{
		FileWidget* fw = (FileWidget*)m_files_tab->widget( i );
		if( !fw )
		{
			continue;
		}
		QString fw_path = fw->getPathFile();

		if( fw_path == path_in )
		{
			return -1;
		}
	}

	this->setDisabled( true );
	this->repaint();

	QStringList path_in_folders = path_in.split( "/" );
	QString label = path_in;
	if( path_in_folders.size() > 0 )
	{
		label = path_in_folders.at(path_in_folders.size()-1);
	}
	FileWidget* fw = new FileWidget();
	int index = m_files_tab->addTab( fw, label );
	connect( fw,	SIGNAL( signalFileWidgetLoaded() ), this,	SLOT( slotFileWidgetLoaded() ) );
	connect( this,	SIGNAL( signalSaveAllChanges() ), fw,		SLOT( slotSaveClicked() ) );
	fw->setPathFile( path_in );

	return index;

}
void MainWindow::slotFileWidgetLoaded()
{
	this->setDisabled( false );
}

void MainWindow::slotTabCloseRequested( int index )
{
	m_files_tab->removeTab( index );
	if( m_map_recent_tabindex_tablerow.find( index ) != m_map_recent_tabindex_tablerow.end() )
	{
		int row = m_map_recent_tabindex_tablerow[index];
		m_table_recent_files->cellWidget( row, 1 )->setDisabled( false );
		m_map_recent_tabindex_tablerow.erase( index );
	}

}

void MainWindow::slotParseSchemaClicked()
{
	emit( signalSaveAllChanges() );
	m_txt_out->clear();

	// collect files content
	QStringList schema_files_content;
	for( int i=0; i<m_files_tab->count(); ++i )
	{
		FileWidget* fw = (FileWidget*)m_files_tab->widget( i );
		if( !fw )
		{
			continue;
		}
		QTextEdit* te = fw->getTextEdit();
		schema_files_content << te->toPlainText();
		// TODO: get file name, pass it to class generator
	}

	QString path_out = m_le_path_out->text();
	m_class_generator->setPathOut( path_out );
	m_txt_out->clear();
	m_class_generator->parseSchemaFiles( schema_files_content );
}

void MainWindow::slotTxtOut( QString txt )
{
	m_txt_out->append( "<div style=\"color:black;\">" + txt + "</div><br/>" );
	m_txt_out->repaint();
}

void MainWindow::slotTxtOutWarning( QString txt )
{
	m_txt_out->append( "<div style=\"color:red;\">Warning: " + txt + "</div><br/>" );
}

void MainWindow::keyPressEvent( QKeyEvent* event )
{
	if( event->key() == Qt::Key_F5 )
	{
		slotParseSchemaClicked();
	}
	else if( event->key() == Qt::Key_F6 )
	{
		close();
	}
}

void MainWindow::slotProgressValue( int value )
{
	m_progress_bar->setValue( value );
}

void MainWindow::slotLoadSchemaClicked()
{

	QPushButton* btn_load = (QPushButton*)sender();
	if( !btn_load )
	{
		return;
	}
	if( m_map_btnload_tablerow.find( btn_load ) == m_map_btnload_tablerow.end() )
	{
		return;
	}

	int row = m_map_btnload_tablerow[btn_load];

	if( row < 0 || row >= m_table_schema_files->rowCount() )
	{
		return;
	}

	QString file_name = ":Resources/" + m_table_schema_files->item( row, 0 )->text();
	int index = slotAddSchemaFile( file_name );
	m_table_schema_files->cellWidget( row, 1 )->setDisabled( true );
	//m_map_tabindex_tablerow.insert( std::pair<int,int>(index,row) );
}

void MainWindow::slotLoadRecentFileClicked()
{
	QPushButton* btn_load = (QPushButton*)sender();
	if( !btn_load )
	{
		return;
	}
	if( m_map_btnload_tablerow.find( btn_load ) == m_map_btnload_tablerow.end() )
	{
		return;
	}

	int row = m_map_btnload_tablerow[btn_load];

	if( row < 0 || row >= m_recent_files.size() )
	{
		return;
	}

	QString file_name = m_recent_files.at( row );// m_table_recent_files->item( row, 0 )->text();
	int index = slotAddSchemaFile( file_name );
	m_table_recent_files->cellWidget( row, 1 )->setDisabled( true );
	//m_map_tabindex_tablerow.insert( std::pair<int,int>(index,row) );
}

void MainWindow::slotIncludeComments( int state )
{
	if( state == Qt::Checked )
	{
		m_class_generator->m_include_comments = true;
	}
	else
	{
		m_class_generator->m_include_comments = false;
	}
}
